#include "CPlaneCamera.h"
#include "CGlobals.h"
#include "CLevelEditor.h"
#include "CUserInterface.h"
#include "ICameraSceneNode.h"
#include "IVideoDriver.h"
#include <cmath>
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
extern CGlobals* g;
extern CLevelEditor* editor;
extern CUserInterface* ui;
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
CPlaneCameraAnimator::CPlaneCameraAnimator (ICameraSceneNode* camera, vector3df e1, vector3df e2)
	:m_leftMousePressed(false)
{
	m_camera = camera;
	m_e1 = e1;
	m_e2 = e2;
	m_rightMousePressed = false;

	m_zoom = 1000.0f;

	m_e1_save = m_e1;
	m_e2_save = m_e2;
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
bool CPlaneCameraAnimator::isEventReceiverEnabled () const
{
	return true;
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
bool CPlaneCameraAnimator::OnEvent (const SEvent& event)
{
	switch (event.EventType)
	{
		case EET_KEY_INPUT_EVENT:
			if(event.KeyInput.Key==irr::KEY_BACK)
			{
				m_e1 = m_e1_save;
				m_e2 = m_e2_save;
			}
			break;

		case EET_MOUSE_INPUT_EVENT:
			switch (event.MouseInput.Event)
			{
				case EMIE_MOUSE_WHEEL:
				{
					float factor = std::abs(m_zoom) / 15.0f;
					if (factor > 1.0f) factor = std::pow(factor, 1.2f);
					else factor = 1.0f;
					
					m_zoom -= factor * event.MouseInput.Wheel;
					if(m_zoom>100000)
						m_zoom=100000;
					else if(m_zoom<1000)
						m_zoom = 1000;
					
					return true;
				}

				case EMIE_LMOUSE_PRESSED_DOWN:
					m_leftMousePressed = true;
					m_mouseStartPos = position2di(event.MouseInput.X, event.MouseInput.Y);
					m_cameraStartPos = m_camera->getTarget();
					return true;

				case EMIE_LMOUSE_LEFT_UP:
					m_leftMousePressed = false;
					return true;					

				case EMIE_RMOUSE_PRESSED_DOWN:
					m_rightMousePressed = true;
					m_mouseStartPos = position2di(event.MouseInput.X, event.MouseInput.Y);
					m_cameraStartPos = m_camera->getTarget();
					return true;

				case EMIE_RMOUSE_LEFT_UP:
					m_rightMousePressed = false;
					return true;

				case EMIE_MOUSE_MOVED:
					if (m_rightMousePressed)
					{
						vector3df moveBy = 0.001f * m_zoom *
							((event.MouseInput.X - m_mouseStartPos.X) * m_e2 +
							 (event.MouseInput.Y - m_mouseStartPos.Y) * m_e1);
						m_camera->setTarget(m_cameraStartPos + moveBy);
						
						return true;
					}

					//by dai_yx
					//if(m_leftMousePressed)
					//{
					//	float angle = (event.MouseInput.Y - m_mouseStartPos.Y)*0.001f ;
					//	//vector3df lookat = m_e1.crossProduct(m_e2); 
					//	vector3df lookat = m_camera->getTarget()-m_camera->getPosition();
					//	lookat.normalize();
					//	irr::core::quaternion rot;
					//	rot.fromAngleAxis(angle,lookat);						
					//	m_e1 = rot*m_e1;
					//	m_e1.normalize();	
					//	m_e2 = rot*m_e2;
					//	m_e2.normalize();

					//	return true;
					//}
					break;
			}
			break;
	}
	return false;
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void CPlaneCameraAnimator::animateNode (ISceneNode* node, u32 timeMs)
{
	vector3df up = m_e1; up.normalize();
	vector3df lookat = m_e1.crossProduct(m_e2); lookat.normalize();
	vector3df target = m_camera->getTarget();

	m_camera->setPosition(target - m_zoom * lookat);
	m_camera->setUpVector(up);
	m_camera->updateAbsolutePosition();

	matrix4 proj;
	float scale = 0.001f * m_zoom;
	const dimension2d<u32> test = g->driver->getCurrentRenderTargetSize();
	proj.buildProjectionMatrixOrthoLH(
		scale * g->driver->getCurrentRenderTargetSize().Width,
		scale * g->driver->getCurrentRenderTargetSize().Height, 0.05f, 150000.0f);
	m_camera->setProjectionMatrix(proj , true);
	//m_camera->render();
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void CPlaneCameraAnimator::setZoom ()
{
	vector3df up = m_e1; up.normalize();
	vector3df lookat = m_e1.crossProduct(m_e2); lookat.normalize();

	vector3df dist = (m_camera->getTarget() - m_camera->getPosition());

	if(lookat.Z != 0)
	{
		setZoom(dist.Z / lookat.Z);
	}
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void CPlaneCameraAnimator::setZoom (float zoom)
{
	if (m_zoom < 0.0f)
		zoom = -std::abs(zoom);
	else
		zoom = std::abs(zoom);
	m_zoom = zoom;
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------